/*
 * Copyrignt (c) xuzeshui.com. All Rights Reserved.
 * Author: Zeshui Xu<i@xuzeshui.com>
 * Created Time: 2015-09-29 21:12:16
 * Last Modified: 2017-06-02 16:42:41
 * File Name: account/account.go
 * Description:
 */
package account

import (
	"fmt"

	"passport/models"

	log "github.com/cihub/seelog"
	"github.com/garyburd/redigo/redis"
)

/*
	ThirdAccount标识
*/
const (
	AI_SELF_ACCOUNT  int8 = 0
	AI_THIRD_ACCOUNT int8 = 1
)

/*
	BindStatus标识
*/
const (
	AI_BIND_STATUS   int8 = 1
	AI_UNBIND_STATUS int8 = 0
)

/*
	Activeu状态
*/
const (
	AI_ACTIVE_ALLOW_LOGIN int8 = 1
	AI_ACTIVE_NOLOGIN     int8 = 0
)

/*
	ExtFrom标识定义
*/
const (
	//指尖到家
	ACCOUNT_TYPE_QQ     string = "qq"
	ACCOUNT_TYPE_WECHAT string = "wechat"
	ACCOUNT_TYPE_WEIBO  string = "weibo"
	//轻客
	ACCOUNT_TYPE_QQ_QK        string = "qkqq"
	ACCOUNT_TYPE_WECHAT_QK    string = "qkwechat"
	ACCOUNT_TYPE_WEIBO_QK     string = "qkweibo"
	ACCOUNT_TYPE_WECHATWEB_QK string = "qkwechatweb"

	ACCOUNT_TYPE_COOCAA      string = "coocaa"
	ACCOUNT_TYPE_MOBILE      string = "mobile"
	ACCOUNT_TYPE_EMAIL       string = "email"
	Account_TYPE_INVITE_CODE string = "ic"
	ACCOUNT_TYPE_JDXG        string = "jdxg"

	ACCOUNT_TYPE_UNI_WECHAT string = "uni_wechat"
)

/*
	账号标识是否正确
*/
func IsValidAccountType(at string) bool {
	return IsSelfAccountType(at) || IsThirdAccountType(at)
}

/*
	是哪种uniaccount
*/
func UniAccountType(at string) string {
	if ACCOUNT_TYPE_WECHAT == at ||
		ACCOUNT_TYPE_JDXG == at ||
		ACCOUNT_TYPE_WECHAT_QK == at ||
		ACCOUNT_TYPE_WECHATWEB_QK == at {
		return ACCOUNT_TYPE_UNI_WECHAT
	}
	return ""
}

/*
	是否是第三方账号
*/
func IsThirdAccountType(at string) bool {
	return ACCOUNT_TYPE_QQ == at ||
		ACCOUNT_TYPE_WECHAT == at ||
		ACCOUNT_TYPE_WEIBO == at ||
		ACCOUNT_TYPE_COOCAA == at ||
		ACCOUNT_TYPE_JDXG == at ||
		ACCOUNT_TYPE_UNI_WECHAT == at ||
		ACCOUNT_TYPE_QQ_QK == at ||
		ACCOUNT_TYPE_WECHAT_QK == at ||
		ACCOUNT_TYPE_WEIBO_QK == at ||
		ACCOUNT_TYPE_WECHATWEB_QK == at
}

func IsSelfAccountType(at string) bool {
	return ACCOUNT_TYPE_MOBILE == at
}

var (
	accountService     *AccountService
	accessTokenService *AccessTokenService
	accountBindService *AccountBindService
)

/*
	账号信息数据结构
*/
type AccountInfo struct {
	Account      string `redis:"account"`       //账号
	AccountType  string `redis:"account_type"`  //账号类型
	Active       int8   `redis:"active"`        //账号是否激活
	NickName     string `redis:"nick_name"`     //关联的账号昵称,针对第三方
	Userid       string `redis:"userid"`        //对应的userid
	ThirdAccount int8   `redis:"third_account"` //是否第三方账号,1:第三方账号;0:自有账号
	BindStatus   int8   `redis:"bind_status"`   //绑定状态,1:绑定;0:未绑定
	InsertTime   string `redis:"insert_time"`   //插入时间
	UpdateTime   string `redis:"update_time"`   //更新时间
}

/*
	账号是否被冻结,禁止登陆
*/
func (p *AccountInfo) IsFreezed() bool {
	return p.Active == AI_ACTIVE_NOLOGIN
}

/*
	账号是否绑定
*/
func (p *AccountInfo) IsBinded() bool {
	return p.BindStatus == AI_BIND_STATUS
}

/*
	AccountService
*/
type AccountService struct{}

/*
	AccountInfo在redis中的存储key
*/
func (p *AccountService) GetAccountKey(extFrom, extId string) string {
	return fmt.Sprintf("a:%s-%s", extFrom, extId)
}

/*
	获取userid
*/
func (p *AccountService) GetUseridFromAccount(extFrom, extId string) (string, error) {
	accountKey := p.GetAccountKey(extFrom, extId)
	conn := models.GetPassportModel().Get()
	defer conn.Close()
	if reply, err := redis.String(conn.Do("hget", accountKey, "userid")); err == nil {
		return reply, nil
	} else if redis.ErrNil == err {
		return "", nil
	} else {
		log.Errorf("cmd: hget %s userid, msg: %s", accountKey, err.Error())
		return "", err
	}
}

/*
	更新账号信息
*/
func (p *AccountService) setAnyAccountInfoByMap(extFrom, extId string, v map[string]interface{}) error {
	accountKey := p.GetAccountKey(extFrom, extId)
	conn := models.GetPassportModel().Get()
	defer conn.Close()
	_, err := conn.Do("hmset", redis.Args{}.Add(accountKey).AddFlat(v)...)
	return err
}

/*
	删除账号信息
*/
func (p *AccountService) deleteAccountInfo(extFrom, extId string) error {
	accountKey := p.GetAccountKey(extFrom, extId)
	conn := models.GetPassportModel().Get()
	defer conn.Close()
	_, err := conn.Do("del", accountKey)
	return err
}

/*
	获取accountinfo
	返回error表示出错,若无error但第一参数为空,表示不存在
*/
func (p *AccountService) GetAllAccountInfo(extFrom, extId string) (*AccountInfo, error) {
	accountKey := p.GetAccountKey(extFrom, extId)
	conn := models.GetPassportModel().Get()
	defer conn.Close()
	var accountInfo AccountInfo
	if reply, err := redis.Values(conn.Do("hgetall", accountKey)); err == nil {
		if len(reply) == 0 { //无纪录,会回返成功,但reply为0长度
			return nil, nil
		}

		if err := redis.ScanStruct(reply, &accountInfo); err == nil {
			return &accountInfo, nil
		} else {
			return nil, err
		}
	} else if redis.ErrNil == err {
		return nil, nil
	} else {
		return nil, err
	}
}

/*
	设置AccountInfo信息
*/
func (p *AccountService) SetAllAccountInfo(accountInfo *AccountInfo) error {
	accountKey := p.GetAccountKey(accountInfo.AccountType, accountInfo.Account)
	conn := models.GetPassportModel().Get()
	defer conn.Close()
	_, err := conn.Do("hmset", redis.Args{}.Add(accountKey).AddFlat(accountInfo)...)
	return err
}

/*
	AccountService处理对象
*/
func GetAccountService() *AccountService {
	return accountService
}

/*
	AccessTokenService处理对象
*/
func GetAccessTokenService() *AccessTokenService {
	return accessTokenService
}

/*
	AccountBindService处理对象
*/

func GetAccountBindService() *AccountBindService {
	return accountBindService
}

func init() {
	accountService = &AccountService{}
	accessTokenService = &AccessTokenService{}
	accountBindService = &AccountBindService{}
}
